package com.chenfan.process.biz.impl;

import com.alibaba.fastjson.JSONObject;
import com.chenfan.infra.context.UserContextHolder;
import com.chenfan.infra.vo.UserVO;
import com.chenfan.notify.dto.NotifyDTO;
import com.chenfan.process.context.ApprovalEventContext;
import com.chenfan.process.context.CounterSignContext;
import com.chenfan.process.context.NotifyEventContext;
import com.chenfan.process.dto.ApprovalCallBack;
import com.chenfan.process.entity.po.ApprovalPo;
import com.chenfan.process.entity.po.ApprovalTemplatePo;
import com.chenfan.process.entity.po.ProcessInstanceApprovePo;
import com.chenfan.process.entity.po.TemplateConfigPo;
import com.chenfan.process.enums.ApprovalMessageTypeEnum;
import com.chenfan.process.enums.EventTypeEnums;
import com.chenfan.process.event.callback.CallbackEvent;
import com.chenfan.process.event.callback.NotifyEvent;
import com.chenfan.process.event.callback.TriggerCallbackEvent;
import com.chenfan.process.event.callback.TriggerCallbackEventData;
import com.chenfan.process.service.impl.NotifyDomainService;
import com.chenfan.process.util.MessageCenterHelper;
import com.chenfan.process.util.TransactionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author K
 * @date 2021-05-11
 */
@Slf4j
@Component
public class EventPublisherBiz extends BaseEventBiz {

    public void publishEvent(ApprovalCallBack.ApprovalCallBackBuilder builder, Long approvalId,
        Boolean approvalFinishFlag, Boolean approvalFlag, String nextApprovalUserId, String nextApprovalUserName,
        Integer eventType, String remark, Long approvalTemplateId, Long currentProcessId) {
        ApprovalPo approval = approvalService.findApprovalByApprovalId(approvalId);

        if (Objects.nonNull(currentProcessId)) {
            List<ApprovalCallBack.CarbonCopyDTO> processList =
                carbonCopyList(approval, approvalTemplateId, currentProcessId);
            builder.carbonCopyList(processList);
        }

        UserVO userVo = UserContextHolder.getUserVo();

        if (Objects.nonNull(userVo)) {
            builder.userId(userVo.getUserId());
            builder.userName(userVo.getRealName());
        }

        boolean needSend = true;
        // 审批通过, 且结束.
        if (Boolean.TRUE.equals(approvalFinishFlag) && Boolean.TRUE.equals(approvalFlag)) {
            // 查询最后一个
            needSend = dealWithEvent(approvalId, approvalTemplateId, currentProcessId);
        }

        if (needSend) {
            CallbackEvent callbackEvent = new CallbackEvent(
                    builder.approvalFinished(approvalFinishFlag).approvalFlag(approvalFlag)
                            .nextApprovalUserId(nextApprovalUserId).nextApprovalUserName(nextApprovalUserName)
                            .eventType(eventType).remark(remark).approvalId(approvalId).build(),
                    UserContextHolder.getToken());
            TransactionUtils.afterCommit(() -> publisher.publishEvent(callbackEvent));
        }
    }


    public ApprovalCallBack generateEvent(ApprovalPo approvalPo) {
        ApprovalCallBack approvalCallBack = new ApprovalCallBack();
        approvalCallBack.setApprovalId(approvalPo.getApprovalId());
        approvalCallBack.setApprovalFlag(Boolean.TRUE);
        approvalCallBack.setParam(approvalPo.getParam());
        approvalCallBack.setEventType(EventTypeEnums.APPROVAL.getCode());
        approvalCallBack.setServiceName(approvalPo.getServiceName());
        // 设置下个审批人
        if (!approvalPo.isFinish()) {
            approvalCallBack.setNextApprovalUserId(approvalPo.getUserId());
            approvalCallBack.setNextApprovalUserName(approvalPo.getUserName());
        }


        UserVO userVo = UserContextHolder.getUserVo();
        if (Objects.nonNull(userVo)) {
            // 设置当前操作的人
            approvalCallBack.setUserId(userVo.getUserId());
            approvalCallBack.setUserName(userVo.getRealName());
        }

        // 生成事件等待发布
        return approvalCallBack;
    }

    public void triggerEvent() {
        // 是否要落库支持重试?
        TriggerCallbackEvent event = ApprovalEventContext.getEvent();

        if (Objects.nonNull(event) && !CollectionUtils.isEmpty(event.getTriggerCallbackEventDataList())) {
            log.info("触发回调事件, 参数:{}", JSONObject.toJSONString(event.getTriggerCallbackEventDataList()));
            ApprovalPo approvalPo = event.getTriggerCallbackEventDataList().get(0).getApprovalPo();
            ApprovalTemplatePo templatePo = approvalTemplateService.getById(approvalPo.getApprovalTemplateId());
            TemplateConfigPo config = templateConfigService.getByTemplateId(approvalPo.getApprovalTemplateId(), approvalPo.getVersion());

            if (Boolean.TRUE.equals(config.getCcNotify())) {
                for (TriggerCallbackEventData triggerCallbackEventData : event.getTriggerCallbackEventDataList()) {
                    sendDefaultCCMessage(triggerCallbackEventData.getApprovalPo(), triggerCallbackEventData.getApprovalCallBack(), templatePo, config);
                }
            }
            publisher.publishEvent(event);
        }
        ApprovalEventContext.clear();
    }

    public void triggerNotify(ApprovalPo approvalPo) {
        ApprovalTemplatePo approvalTemplatePo = approvalTemplateService.getById(approvalPo.getApprovalTemplateId());
        TemplateConfigPo templateConfigPo = templateConfigService.getByTemplateId(approvalTemplatePo.getId(), approvalPo.getVersion());
        List<ProcessInstanceApprovePo> approvePoList = instanceApproveService.listApprovingInstances(Collections.singletonList(approvalPo.getApprovalId()));
        log.info("触发生成待办！AutoNotify = {}, CounterSignContext = {}", templateConfigPo.getAutoNotify(), CounterSignContext.getValue());
        // 不允许的情况
        if (Boolean.FALSE.equals(templateConfigPo.getAutoNotify())) {
            return;
        }
        // 允许, 但属于会签的情况
        if(Boolean.TRUE.equals(CounterSignContext.getValue())) {
            return;
        }
        List<NotifyDTO> notifyList = NotifyDomainService.notifyDTO(
                approvalPo, templateConfigPo, approvalTemplatePo, approvePoList
        );

        NotifyEventContext.addEvent(notifyList);
        NotifyEvent notifyEvent = NotifyEventContext.getEvent();

        if (Objects.nonNull(notifyEvent) && !CollectionUtils.isEmpty(notifyEvent.getNotifyList())) {
            publisher.publishEvent(notifyEvent);
        }
        NotifyEventContext.clear();
    }

    private void sendDefaultCCMessage(ApprovalPo approvalPo, ApprovalCallBack approvalCallBack, ApprovalTemplatePo templatePo, TemplateConfigPo config) {
        List<ApprovalCallBack.CarbonCopyDTO> carbonCopyList = approvalCallBack.getCarbonCopyList();
        if (!CollectionUtils.isEmpty(carbonCopyList)) {
            //发送默认消息模板-审批抄送
            MessageCenterHelper.sendDefault(ApprovalMessageTypeEnum.APPROVAL_CC, templatePo, approvalPo,
                    carbonCopyList.stream().map(ApprovalCallBack.CarbonCopyDTO::getUserId).collect(Collectors.toList()),
                    config, null);
        }
    }
}
